vs2015编译tcmalloc(gperftools2.4)

您所在的位置:网站首页 error c2371重定义不同的基类型 vs2015编译tcmalloc(gperftools2.4)

vs2015编译tcmalloc(gperftools2.4)

#vs2015编译tcmalloc(gperftools2.4)| 来源: 网络整理| 查看: 265

TcMalloc(Thread-CachingMalloc)是google-perftools工具中的一个内存管理库,所以一般提到tcmalloc,其实就是指使用gperftools,编译tcmalloc也就是编译gperftools。 第一次使用tcmalloc,网上找了好多关于使用tcmalloc的文章,都讲到了如何安装,如何使用,对于编译都是一笔带过。。。但是是真正实战的时候,发现如果对tcmalloc的代码结构不熟悉,这编译tcmalloc也是不小的坑。本文不涉及安装和使用,只根据自己今天的实际经历说说如何在在windows平台用msvc(准确地说是VS2015)编译tcmalloc。

下载

首先在官网下载gperftools,下载地址为:https://github.com/gperftools/gperftools , 我下载的是最新的:gperftools-2.4.zip

哦,忘记说了,因为GFW的原因,google.com被挡了,如果你还不会访问国外网站,就无法去google官网下载gperftools,

如下图点击”Branch”出现下拉菜单在这里选择你要下载的版本:

这里写图片描述这里写图片描述编译报错

zip包下载解压后是如下图的文件结构:

这里写图片描述这里写图片描述

此压缩包内含README_windows.txt说明文档,该文档包含详细使用教程。gperftools.sln则是MSVC工程文件, 根据gperftools源码包中的README_windows.txt说明,gperftools可以在VC++ 7.1(Visual Studio 2003)或以后的版本中运行。

You can load this solution file into VC++ 7.1 (Visual Studio 2003) or later – in the latter case, it will automatically convert the files to the latest format for you. (README_windows.txt中原文)

我现在用的VisualStudio 最新版本 visual studio 2015,所以应该是可以正常编译gperftools的,于是我用VS2015打开gperftools.sln,按提示将gperftools.sln转成了vs2015格式的。

这里写图片描述这里写图片描述

然后按ctrl+shift+B编译整个工程。。。报出无数错误。。。

1>—— 已启动生成: 项目: libtcmalloc_minimal, 配置: Debug Win32 —— 2>—— 已启动生成: 项目: addressmap_unittest, 配置: Debug Win32 —— 3>—— 已启动生成: 项目: low_level_alloc_unittest, 配置: Debug Win32 —— 4>—— 已启动生成: 项目: tcmalloc_minimal_unittest-static, 配置: Debug Win32 —— 2> dynamic_annotations.c 1> dynamic_annotations.c 3> dynamic_annotations.c 4> dynamic_annotations.c 2>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 2> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 4>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 4> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 3>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 3> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 1>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 1> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 5>—— 已启动生成: 项目: addr2line-pdb, 配置: Debug Win32 —— 6>—— 已启动生成: 项目: nm-pdb, 配置: Debug Win32 —— 7>—— 已启动生成: 项目: tcmalloc_minimal_unittest, 配置: Debug Win32 —— 8>—— 已启动生成: 项目: tcmalloc_minimal_large_unittest, 配置: Debug Win32 —— 6> nm-pdb.c 5> addr2line-pdb.c 8> tcmalloc_large_unittest.cc 7> testutil.cc 6>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(1544): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧 6>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(3190): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧 6>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\nm-pdb.c(113): warning C4474: printf: 格式字符串中传递的参数太多 6> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\nm-pdb.c(113): note: placeholders and their parameters expect 1 variadic arguments, but 2 were provided 5>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(1544): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧 5>c:\program files (x86)\windows kits\8.1\include\um\dbghelp.h(3190): warning C4091: “typedef ”: 没有声明变量时忽略“”的左侧 6>nm-pdb.obj : warning LNK4075: 忽略“/EDITANDCONTINUE”(由于“/SAFESEH”规范) 5>addr2line-pdb.obj : warning LNK4075: 忽略“/EDITANDCONTINUE”(由于“/SAFESEH”规范) 7>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 7> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 7> tcmalloc_unittest.cc 8>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): error C2371: “int8_t”: 重定义;不同的基类型 8> c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): note: 参见“int8_t”的声明 8>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 8> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 9>—— 已启动生成: 项目: frag_unittest, 配置: Debug Win32 —— 7>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 7> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 7>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 7> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 7> 正在生成代码… 9> frag_unittest.cc 9>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 9> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 9>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 9> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 10>—— 已启动生成: 项目: malloc_hook_test, 配置: Debug Win32 —— 11>—— 已启动生成: 项目: malloc_extension_test, 配置: Debug Win32 —— 10> testutil.cc 11> malloc_extension_test.cc 6> nm-pdb.vcxproj -> D:\os.package\cpp\gperftools\gperftools-2.4\Debug\nm-pdb.exe 12>—— 已启动生成: 项目: markidle_unittest, 配置: Debug Win32 —— 5> addr2line-pdb.vcxproj -> D:\os.package\cpp\gperftools\gperftools-2.4\Debug\addr2line-pdb.exe 13>—— 已启动生成: 项目: current_allocated_bytes_test, 配置: Debug Win32 —— 12> testutil.cc 10>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 11>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 10> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 11> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 10> malloc_hook_test.cc 11>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 11> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 12>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 12> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 12> markidle_unittest.cc 10>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 10> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 13> current_allocated_bytes_test.cc 10>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 14>—— 已启动生成: 项目: packed-cache_test, 配置: Debug Win32 —— 10> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 13>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 13> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 13>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 13> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 12>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 12> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 14> packed-cache_test.cc 12>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 12> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 10>c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\time.h(39): error C2011: “timespec”:“struct”类型重定义 10> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(440): note: 参见“timespec”的声明 10> 正在生成代码… 15>—— 已启动生成: 项目: pagemap_unittest, 配置: Debug Win32 —— 14>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 14> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 14>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 14> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 14>d:\os.package\cpp\gperftools\gperftools-2.4\src\packed-cache-inl.h(224): warning C4293: “—— 已启动生成: 项目: page_heap_test, 配置: Debug Win32 —— 17>—— 已启动生成: 项目: realloc_unittest, 配置: Debug Win32 —— 17> realloc_unittest.cc 16> page_heap_test.cc 12> 正在生成代码… 15> pagemap_unittest.cc 15>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 15> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 15>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 15> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 18>—— 已启动生成: 项目: sampler_test, 配置: Debug Win32 —— 19>—— 已启动生成: 项目: stack_trace_table_test, 配置: Debug Win32 —— 17>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 17> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 17>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 17> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 16>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 16> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 18> sampler_test.cc 16>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 16> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 20>—— 已启动生成: 项目: thread_dealloc_unittest, 配置: Debug Win32 —— 21>—— 已跳过生成: 项目: preamble_patcher_test, 配置: Debug Win32 —— 21>没有为此解决方案配置选中要生成的项目 22>—— 已启动生成: 项目: system-alloc_unittest, 配置: Debug Win32 —— 18>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 18> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 18>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 18> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 20> thread_dealloc_unittest.cc 20>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 20> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 20>c:\program files (x86)\microsoft visual studio 14.0\vc\include\stdint.h(17): error C2371: “int8_t”: 重定义;不同的基类型 20> d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(104): note: 参见“int8_t”的声明 20> testutil.cc 20>d:\os.package\cpp\gperftools\gperftools-2.4\src\windows\port.h(328): error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 20> c:\program files (x86)\windows kits\10\include\10.0.10150.0\ucrt\stdio.h(1932): note: 参见“snprintf”的前一个定义 20> 正在生成代码… ========== 生成: 成功 2 个,失败 19 个,最新 0 个,跳过 1 个 ==========

修改config.h

看到上面的一大堆报错,脑子一下子就晕了,尼玛,什么玩意儿,编译器支持这么差?没有说明不支持vs编译器啊。 仔细分析上面的错误信息,发现主要就是snprintf、int8_t和timespec重定义,

error C2084: 函数“int snprintf(char *const ,const size_t,const char *const ,…)”已有主体 error C2371: “int8_t”: 重定义;不同的基类型 error C2011: “timespec”:“struct”类型重定义

考虑到vs2015比较新,用google搜索了一下”tcmalloc vs2010”,发现了这篇文章《TCMalloc static lib in vs2010》

文中解决的问题我并不关心,但我发现了这个:(#define WIN32_OVERRIDE_ALLOCATORS in config.h). 打开gperftools的源文件夹,在/src/windows下面果然发现找到了文中提到的config.h以及提到的宏定义WIN32_OVERRIDE_ALLOCATORS

这里写图片描述这里写图片描述这里写图片描述这里写图片描述

我才明白,gpreftools为了能根据需要编译出不特性的代码,以及适应在不同版本的编译器下正常编译,设计了这个config.h通过宏定义来控制代码生成。在不同的编译器下编译,要根据编译报错的信息来相应修改config.h来解决。上图中最后一行,就是关于snprintf的

/* Define to 1 if your libc has a snprintf implementation */ #undef HAVE_SNPRINTF

根据注释的说明,如果编译已经有snprintf 的实现,就要将HAVE_SNPRINTF定义为1

根据 www.cplusplus.com上关于snprintf的说明,snprintf是C++11支持的函数 VS2015版本已经有了snprintf的实现,所以要修改config.h中HAVE_SNPRINTF的定义

/* Define to 1 if your libc has a snprintf implementation */ #define HAVE_SNPRINTF 1

同样的道理,关于int8_t,也是因为int8_t所在的文件已经是C++11的标准头文件,参见 (stdint.h)。

在config.h中找到下面的定义

/* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H

改为

/* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1

至于timespec也是因为定义在port.h中的timespec与c++标准头文件time.h中的timespec定义重复

这是port.h中的关于timespec的代码片段,看代码注释,是因为mingw没有定义timespc,而且mingw64中有定义,所以有点混乱,所以在这里用_TIMESPEC_DEFINED来做一个保护

// mingw64 seems to define timespec (though mingw.org mingw doesn't), // protected by the _TIMESPEC_DEFINED macro. #ifndef _TIMESPEC_DEFINED struct timespec { int tv_sec; int tv_nsec; }; #endif

而在是通过_CRT_NO_TIME_T来控制是否定义timespec

#ifndef _CRT_NO_TIME_T struct timespec { time_t tv_sec; // Seconds - >= 0 long tv_nsec; // Nanoseconds - [0, 999999999] }; #endif

所以在config.h中加入下面一行,以去掉time.h中的timespec定义

#define _CRT_NO_TIME_T 1

最后保存config.h再编译,就可以通过了。

但是,编译通过只是第一步,是否能真的正常使用,还有待后面工作进行验证。

结论

要正确编译tcmalloc,应该根据c++编译器类型和版本的不同,修改config.h以达到与编译工具最匹配的状态,config.h中还有很多选项没有仔细研究,需要进一步深入了解。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3